package com.hrm.system.service;

import com.hrm.common.entity.ResultCode;
import com.hrm.common.exception.CommonException;
import com.hrm.common.utils.BeanMapUtils;
import com.hrm.common.utils.IdWorker;
import com.hrm.common.utils.PermissionConstants;
import com.hrm.domain.system.Permission;
import com.hrm.domain.system.PermissionApi;
import com.hrm.domain.system.PermissionMenu;
import com.hrm.domain.system.PermissionPoint;
import com.hrm.system.dao.PermissionApiDao;
import com.hrm.system.dao.PermissionDao;
import com.hrm.system.dao.PermissionMenuDao;
import com.hrm.system.dao.PermissionPointDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author: 林海湾Sea
 * @Date :  2021/11/25 19:30
 * @Decription: 权限操作业务逻辑层
 */
@Service
public class PermissionService {

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private PermissionDao permissionDao;

    @Autowired
    private PermissionApiDao permissionApiDao;

    @Autowired
    private PermissionMenuDao permissionMenuDao;

    @Autowired
    private PermissionPointDao permissionPointDao;

    /**
     * 1、保存权限
     */
    public void save(Map<String, Object> map) throws Exception {

        // 设置主键的值
        String id = idWorker.nextId()+"";
        // 1、通过map构造permission对象
        Permission permission = BeanMapUtils.mapToBean(map, Permission.class);
        permission.setId(id);
        // 2、根据类型构造不同的资源对象（菜单、按钮、api）
        int type = permission.getType();
        switch(type) {
            case PermissionConstants.PERMISSION_MENU:
                PermissionMenu menu = BeanMapUtils.mapToBean(map, PermissionMenu.class);
                menu.setId(id);
                permissionMenuDao.save(menu);
                break;

            case PermissionConstants.PERMISSION_POINT:
                PermissionPoint point = BeanMapUtils.mapToBean(map, PermissionPoint.class);
                point.setId(id);
                permissionPointDao.save(point);
                break;

            case PermissionConstants.PERMISSION_API:
                PermissionApi api = BeanMapUtils.mapToBean(map, PermissionApi.class);
                api.setId(id);
                permissionApiDao.save(api);
                break;

            default:
                throw new CommonException(ResultCode.FAIL);
        }
        // 3、保存
        permissionDao.save(permission);
    }

    /**
     * 2、更新权限
     */
    public void update(Map<String, Object> map) throws Exception {
        Permission permission = BeanMapUtils.mapToBean(map, Permission.class);
        // 1、通过传递的权限id查询权限
        Permission targetPermission = permissionDao.findById(permission.getId()).get();
        targetPermission.setName(permission.getName());
        targetPermission.setCode(permission.getCode());
        targetPermission.setDescription(permission.getDescription());
        targetPermission.setEnVisible(permission.getEnVisible());

        // 2、根据类型，构造不同的资源
        int type = permission.getType();
        switch(type) {
            case PermissionConstants.PERMISSION_MENU:
                PermissionMenu menu = BeanMapUtils.mapToBean(map,PermissionMenu.class);
                menu.setId(permission.getId());
                permissionMenuDao.save(menu);
                break;
            case PermissionConstants.PERMISSION_POINT:
                PermissionPoint point = BeanMapUtils.mapToBean(map,PermissionPoint.class);
                point.setId(permission.getId());
                permissionPointDao.save(point);
                break;
            case PermissionConstants.PERMISSION_API:
                PermissionApi api = BeanMapUtils.mapToBean(map,PermissionApi.class);
                api.setId(permission.getId());
                permissionApiDao.save(api);
                break;
            default:
                throw new CommonException(ResultCode.FAIL);
        }

        permissionDao.save(permission);

    }

    /**
     * 3、根据Id查询权限
     *    1、查询权限
     *    2、根据权限的类型查询资源
     *    3、构造map集合
     */
    public Map<String, Object> findById(String id) throws Exception {
        Permission permission = permissionDao.findById(id).get();
        int type = permission.getType();
        Object object = null;

        if (type == PermissionConstants.PERMISSION_MENU) {
            object = permissionMenuDao.findById(id).get();
        } else if(type == PermissionConstants.PERMISSION_POINT) {
            object = permissionPointDao.findById(id).get();
        } else if(type == PermissionConstants.PERMISSION_API) {
            object = permissionApiDao.findById(id).get();
        } else {
            throw new CommonException(ResultCode.FAIL);
        }

        Map<String, Object> map = BeanMapUtils.beanToMap(object);

        map.put("name", permission.getName());
        map.put("type", permission.getType());
        map.put("code", permission.getCode());
        map.put("description", permission.getDescription());
        map.put("pid", permission.getPid());
        map.put("enVisible", permission.getEnVisible());

        return map;
    }

    /**
     * 4、查询全部权限列表
     *    type:权限类型，0：菜单+按钮（权限点），
     *                 1：菜单
     *                 2：按钮（权限点）
     *                 3：API接口
     *
     *    enVisible : 0：查询所有saas平台的最高权限，
     *                1：查询企业的权限
     *    pid ：父id
     */
    public List<Permission> findAll(Map<String, Object> map) {
        // 1、构造查询条件
        Specification<Permission> spec = new Specification<Permission>() {
            /**
             * 动态拼接实现查询条件
             * @param root
             * @param criteriaQuery
             * @param criteriaBuilder
             * @return
             */
            @Override
            public Predicate toPredicate(Root<Permission> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                List<Predicate> list = new ArrayList<>();
                // 根据父id查询
                if (!StringUtils.isEmpty(map.get("pid"))) {
                    list.add(criteriaBuilder.equal(root.get("pid").as(String.class),map.get("pid")));
                }
                // 根据enVisible查询
                if (!StringUtils.isEmpty(map.get("enVisible"))) {
                    list.add(criteriaBuilder.equal(root.get("enVisible").as(String.class),map.get("enVisible")));
                }
                // 根据类型 type
                if (!StringUtils.isEmpty(map.get("type"))) {
                    String ty = (String) map.get("type");
                    CriteriaBuilder.In<Object> in = criteriaBuilder.in(root.get("type"));
                    if ("0".equals(map.get(ty))) {
                        in.value(1).value(2);
                    } else {
                        in.value(Integer.parseInt(ty));
                    }
                    list.add(in);
                }
                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        };

        return permissionDao.findAll(spec);
    }

    /**
     * 5、根据id删除权限
     *    删除权限
     *    删除权限对应的资源
     */
    public void deleteById(String id) throws Exception {
        // 1、通过传递的权限id查询权限
        Permission permission = permissionDao.findById(id).get();
        permissionDao.delete(permission);
        // 2、查询不同的资源
        int type = permission.getType();
        switch(type) {
            case PermissionConstants.PERMISSION_MENU:
                permissionMenuDao.deleteById(id);
                break;
            case PermissionConstants.PERMISSION_POINT:
                permissionPointDao.deleteById(id);
                break;
            case PermissionConstants.PERMISSION_API:
                permissionApiDao.deleteById(id);
                break;
            default:
                throw new CommonException(ResultCode.FAIL);
        }
    }

    /**
     * 6、分配角色
     */



}
